#
#    Copyright 2006 Andrew Wilkinson <aw@cs.york.ac.uk>.
#
#    This file is part of PyScobble (http://lastfm.indiegigs.co.uk/pyscrobble)
#
#    PyScobble is free software; you can redistribute it and/or modify
#    it under the terms of the GNU Lesser General Public License as published by
#    the Free Software Foundation; either version 2.1 of the License, or
#    (at your option) any later version.
#
#    PyScobble is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU Lesser General Public License for more details.
#
#    You should have received a copy of the GNU Lesser General Public License
#    along with PyScobble; if not, write to the Free Software
#    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
#

import datetime
import md5
import time
import threading
import urllib
import urllib2

from scrobble.artist import Artist
from scrobble.track import Track
from scrobble.user import User
from scrobble.database import getScrobbleCache, addToScrobbleCache
from scrobble.utils import *

lock = threading.Semaphore()
caching = False

sockets = {}

submit_delay = 0

def scrobbleTrack(user, track, time=None):
    global submit_delay
    assert isinstance(user, User), user
    assert isinstance(track, Track), track
    if user.md5passwd is None:
        raise ValueError, "To scrobble tracks the user's password is required"

    if time is None:
        time = datetime.datetime.now()

    lock.acquire()
    try:
        if caching:
            addToScrobbleCache(user, track, time)
            return False
        else:
            s = getConnection(user)
            if s is None:
                return
            delaySubmit()
            url = urllib.urlencode([("user", user.username), ("s", md5.new(user.md5passwd + s[0]).hexdigest()), ("a[0]", track.artist.name), ("t[0]", track.name), ("b[0]", track.albumname or ""), ("m[0]", track.mbid or ""), ("l[0]", track.length or ""), ("i[0]", time.strftime("%Y-%m-%d %H:%M:%S"))]).encode("utf8")
            setStatus(s[1] + " " + url)
            url = urllib2.urlopen(s[1], url)
            text = url.read()
            print text
            text = text.split("\n")
            for line in text:
                setStatus(line)
            if text[0].startswith("OK"):
                if len(text) == 2 and text[1].startswith("INTERVAL"):
                    submit_delay = time.time() + int(text[1][9:])
                return True
            elif text[0].startswith("FAILED"):
                setStatus("Submit failed: %s" % (text[0][7:], ))
                if len(text) == 2 and text[1].startswith("INTERVAL"):
                    submit_delay = time.time() + int(text[1][9:])
                    sockets[user.username] = (s[0], s[1], int(text[1][9:]))
                return False
            elif text[0].startswith("BADAUTH"):
                setStatus("Submit BADAUTH: %s" % (text[0][8:], ))
                if len(text) == 2 and text[1].startswith("INTERVAL"):
                    submit_delay = time.time() + int(text[1][9:])
                    sockets[user.username] = (s[0], s[1], int(text[1][9:]))
                return False
    finally:
        lock.release()

def getConnection(user):
    global submit_delay
    if sockets.has_key(user.username):
        return sockets[user.username]

    setStatus("Logging in as %s." % (user.username, ))
    s = urllib2.urlopen("http://post.audioscrobbler.com/?hs=true&p=1.1&c=%s&v=%s&u=%s" % (client_id, client_version, user.username))
    text = s.read().split("\n")
    for line in text:
        setStatus(line)

    if text[0].startswith("FAILED"):
        setStatus("Submit register failed: %s" % (text[0][7:], ))
        if text[1].startswith("INTERVAL"):
            submit_delay = time.time() + int(text[1][9:])
        return None
    elif text[0].startswith("BADUSER"):
        setStatus("BASUSER: User %s is invalid." % (user.username, ))
        if text[1].startswith("INTERVAL"):
            submit_delay = time.time() + int(text[1][9:])
        return None
    elif text[0].startswith("UPDATE"):
        setStatus("UPDATE: Download update from %s" % (text[0][8:], ))
        challenge = text[1]
        url = text[2]
        delay = int(text[3][9:])
        submit_delay = time.time() + int(delay)
    elif text[0].startswith("UPTODATE"):
        setStatus("Success: %s" % (text[0][9:], ))
        challenge = text[1]
        url = text[2]
        delay = int(text[3][9:])
        submit_delay = time.time() + int(delay)

    sockets[user.username] = (challenge, url, delay)
    setStatus("Success: %s" % (str(sockets[user.username]), ))

    return sockets[user.username]

def delaySubmit():
    global submit_delay
    if submit_delay > time.time():
        time.sleep(submit_delay - time.time())
    submit_delay = time.time()

def checkScrobbleCache():
    if len(getScrobbleCache()) > 0:
        threading.Thread(target=cacheSubmit, args=())

def cacheSubmit():
    pass

checkScrobbleCache()
